# config
"""
Read configuration file.
"""

import os, sys, inspect
from StringIO import StringIO
from ConfigParser import ConfigParser

etc = '/etc/lrv'
source = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
home = os.path.expanduser('~')

def set_unittest_context():
    """
    Special settings for unit testing only (ignores actual user configuration files and uses
    test versions).
    """
    global etc
    global home
    etc = os.path.join(source, 'test', 'etc')
    home = os.path.join(source, 'test', 'home')
    
if __name__ == "__main__":
    set_unittest_context()

CONFIG_DEFAULTS = StringIO("""\
[LibRay]
ThemeDir = {source}/theme/
ArchiveDir = {source}/archive/
Theme = default
Language = und
# MenuLanguage = und
# TextLanguage = und
# AudioLanguage = und
Locale = ZZ
# MenuLocale = ZZ
# TextLocale = ZZ
# AudioLocale = ZZ
Region = TE
""".format(**{'source':source, 'home': home, 'etc': etc}))

# Note the use of reserved codes for language and locale which indicate that
# language and locale are undetermined and will be left 'floating' or 'unset'.
# The language and locale will thus be determined by another source - probably
# the default provided by the current volume.
#
# Menu, Text, and Audio language and locale can be set separately. If so, they will
# override Language and Locale settings.
#
# Note that config format is NOT case-sensitive, capitalization is for clarity only.
  
class Configuration(object):
    """
    Collect configuration file settings.
    
    >>> conf = Configuration()
    >>> conf.menu_lang
    ['und']
    >>> conf.text_lang
    ['en', 'es', 'fr']
    >>> conf.audio_loc
    ['ZZ']
    >>> conf.region
    'TE'
    >>> conf.theme_name
    'default'
  
    """
    version = (0, 4)
    
    # Pull introspected value from module namespace
    etc = etc
    source = source
    home = home
    
    # temp hard-codes for testing
    player_menu_url = "file:///project/terry/Lib-Ray/Dev/lib-ray-video-tools-testfixtures/volumes/0.4/index.html"
    
    player_menu_root = os.path.dirname(player_menu_url)
    
    def __init__(self):
        self.read()

    def read(self):
        # Parse master defaults (set above in this file).
        config = ConfigParser()
        config.readfp(CONFIG_DEFAULTS)
        self.defaults = dict(config.items('LibRay'))
        
        config.read([
            os.path.join(self.source, 'player.cnf'),
            os.path.join(etc, 'player.cnf'),
            os.path.join(self.home, '.lrv', 'player.cnf')
            ])
        self.configured = dict(config.items('LibRay'))
        
        #print self.defaults
        #print self.configured
                
        self.theme_path = config.get('LibRay', 'ThemeDir')      # Location for player menu themes
        self.theme_name = config.get('LibRay', 'Theme')         # Name of theme to use for player menus        
        self.archive_path = config.get('LibRay', 'ArchiveDir')  # Location for volume archive
        self.region = config.get('LibRay', 'Region')            # Map Region for selection menus
        
        # Language preferences may be multiple, so we always represent them this way
        # The list is meant to be in order of descending preference.
        # So if I say I prefer American English, but I understand Castillian Spanish as well
        # I might set
        #
        # Language = en, es
        # Locale = US, ES
        # 
        # The behavior we want is to pick the most preferred track available, with language
        # considered a higher priority than locale:
        #
        # Available: (en_US, en_UK, es_MX) -> Pick en_US
        #            (en_UK, es_ES, es_MX) -> Pick en_UK
        #            (fr_CA, es_MX, es_ES) -> Pick es_ES
        #            (fr_FR, es_MX)        -> Pick es_MX
        #
        # Special values are available:
        #
        # und = "undefined" means to take the first language offered by the volume (which should be
        #       the 'native' language.
        #
        # ZZ  = Likewise for Locale. 
        #
        # Furthermore, Lib-Ray allows different language preferences for Menus,
        # Text tracks (subtitles), and Audio tracks. You can set a single value for
        # all three, or override them individually. We apply a simple cascade rule to
        # find the result for each:
        
        self.menu_lang = []
        self.text_lang = []
        self.audio_lang= []
        self.menu_loc  = []
        self.text_loc  = []
        self.audio_loc = []
        
        self.menu_lang.append(self._cascade('Language', 'MenuLanguage', [self.defaults, self.configured]))
        self.text_lang.append(self._cascade('Language', 'TextLanguage', [self.defaults, self.configured]))
        self.audio_lang.append(self._cascade('Language', 'AudioLanguage', [self.defaults, self.configured]))
        self.menu_loc.append(self._cascade('Locale', 'MenuLocale', [self.defaults, self.configured]))
        self.text_loc.append(self._cascade('Locale', 'TextLocale', [self.defaults, self.configured]))
        self.audio_loc.append(self._cascade('Locale', 'AudioLocale', [self.defaults, self.configured]))
        
        for a in (self.menu_lang, self.text_lang, self.audio_lang, 
                  self.menu_loc, self.text_loc, self.audio_loc):
            if ',' in a[0]:
                data = [i.strip() for i in a[0].split(',')]
                a[:] = data[:]
        
        # We now have lists for each separate setting, according to user preferences in the
        # config files.
             
    def _cascade(self, option_base, option_over, sources):
        result = None
        for source in sources:
            if source.has_key(option_over.lower()):
                result = source[option_over.lower()]
            elif source.has_key(option_base.lower()):
                result = source[option_base.lower()]
        return result
        
# Standard doctest test runner
if __name__ == "__main__":
    print "Running doctest unittests."
    import doctest
    doctest.testmod()
    print "Tests complete."
  
